package rc.alfresco.inflection;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Created with IntelliJ IDEA.
 * UserEntity: simnau
 * Date: 13.2.8
 * Time: 11.26
 * To change this template use File | Settings | File Templates.
 */
public class Inflector {

    /**
     * Inflects a word to the given case
     * @param word the word to inflect
     * @param wordCase case to inflect the word to
     * @return The word inflected to the given case
     */
    public static String getCasedWord(String word, String wordCase){
        String casedWord = "";
        Case caseEnum = Case.caseForName(wordCase);

        if (caseEnum != null){
            switch (caseEnum){
                case GENITIVE:
                    casedWord = getGenitive(word);
                    break;
                case ACCUSATIVE:
                    casedWord = getAccusative(word);
                    break;
                case DATIVE:
                    casedWord = getDative(word);
                    break;
                case INSTRUMENTAL:
                    casedWord = getInstrumental(word);
                    break;
                default:
                    casedWord = "No such case!";
                    break;
            }
        } else {
            casedWord = "No such case!";
        }
        return casedWord;
    }

    /**
     * Inflects a word to the given case
     * @param word the word to inflect
     * @param wordCase case to inflect the word to
     * @return The word inflected to the given case
     */
    public static String getCasedWord(String word, Case wordCase) {
        String casedWord = "";

        if (wordCase != null){
            switch (wordCase){
                case GENITIVE:
                    casedWord = getGenitive(word);
                    break;
                case ACCUSATIVE:
                    casedWord = getAccusative(word);
                    break;
                case DATIVE:
                    casedWord = getDative(word);
                    break;
                case INSTRUMENTAL:
                    casedWord = getInstrumental(word);
                    break;
                default:
                    casedWord = word;
                    break;
            }
        } else {
            casedWord = word;
        }
        return casedWord;
    }

    private static String getGenitive(String wordInNominativeCase) {
        String firstLetter = null;
        boolean isUpper = Character.isUpperCase(wordInNominativeCase.charAt(0));

        wordInNominativeCase = wordInNominativeCase.trim();
        String result = wordInNominativeCase.toLowerCase();

        String[] tokens = wordInNominativeCase.split(" ");

        if(tokens.length > 1){
            result = "";

            for (String token : tokens){
                result += getGenitive(token) + " ";
            }

            result = result.substring(0, result.length() - 1);

            return result;
        } else {
            if (matches(RegularExpressions.FOR_AS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_AS.getCharactersToSubtract());
                result += RegularExpressions.FOR_AS.getGenitiveEnding();

            }  else if (matches(RegularExpressions.FOR_US, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_US.getCharactersToSubtract());
                result += RegularExpressions.FOR_US.getGenitiveEnding();

            } else if (matches(RegularExpressions.FOR_TIS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_TIS.getCharactersToSubtract());
                result += RegularExpressions.FOR_TIS.getGenitiveEnding();

            } else if (matches(RegularExpressions.FOR_IYS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_IYS.getCharactersToSubtract());
                result += RegularExpressions.FOR_IYS.getGenitiveEnding();

            } else if (matches(RegularExpressions.FOR_A, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_A.getCharactersToSubtract());
                result += RegularExpressions.FOR_A.getGenitiveEnding();

            } else if (matches(RegularExpressions.FOR_E, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_E.getCharactersToSubtract());
                result += RegularExpressions.FOR_E.getGenitiveEnding();

            } else if (matches(RegularExpressions.FOR_DYS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_DYS.getCharactersToSubtract());
                result += RegularExpressions.FOR_DYS.getGenitiveEnding();
            }
            else {
                return wordInNominativeCase;
            }
        }

        result = result.toLowerCase();
        if (isUpper) {
            firstLetter = result.substring(0, 1).toUpperCase();
        } else {
            firstLetter = result.substring(0, 1).toLowerCase();
        }
        result = firstLetter + result.substring(1);

        return result;
    }

    private  static String getAccusative(String wordInNominativeCase){
        String firstLetter = null;
        boolean isUpper = Character.isUpperCase(wordInNominativeCase.charAt(0));
        wordInNominativeCase = wordInNominativeCase.trim();
        String result = wordInNominativeCase.toLowerCase();

        String[] tokens = wordInNominativeCase.split(" ");

        if(tokens.length > 1){
            result = "";

            for (String token : tokens){
                result += getAccusative(token) + " ";
            }

            result = result.substring(0, result.length() - 1);

            return result;
        } else {
            if (matches(RegularExpressions.FOR_AS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_AS.getCharactersToSubtract());
                result += RegularExpressions.FOR_AS.getAccusativeEnding();

            } else if (matches(RegularExpressions.FOR_US, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_US.getCharactersToSubtract());
                result += RegularExpressions.FOR_US.getAccusativeEnding();

            } else if (matches(RegularExpressions.FOR_TIS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_TIS.getCharactersToSubtract());
                result += RegularExpressions.FOR_TIS.getAccusativeEnding();

            } else if (matches(RegularExpressions.FOR_IYS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_IYS.getCharactersToSubtract());
                result += RegularExpressions.FOR_IYS.getAccusativeEnding();

            } else if (matches(RegularExpressions.FOR_A, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_A.getCharactersToSubtract());
                result += RegularExpressions.FOR_A.getAccusativeEnding();

            } else if (matches(RegularExpressions.FOR_E, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_E.getCharactersToSubtract());
                result += RegularExpressions.FOR_E.getAccusativeEnding();

            }  else if (matches(RegularExpressions.FOR_DYS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_DYS.getCharactersToSubtract());
                result += RegularExpressions.FOR_DYS.getAccusativeEnding();
            }  else {
                return wordInNominativeCase;
            }
        }

        result = result.toLowerCase();
        if (isUpper) {
            firstLetter = result.substring(0, 1).toUpperCase();
        } else {
            firstLetter = result.substring(0, 1).toLowerCase();
        }
        result = firstLetter + result.substring(1);

        return result;
    }

    private  static String getDative(String wordInNominativeCase){
        String firstLetter = null;
        boolean isUpper = Character.isUpperCase(wordInNominativeCase.charAt(0));
        wordInNominativeCase = wordInNominativeCase.trim();
        String result = wordInNominativeCase.toLowerCase();

        String[] tokens = wordInNominativeCase.split(" ");

        if(tokens.length > 1){
            result = "";

            for (String token : tokens){
                result += getDative(token) + " ";
            }

            result = result.substring(0, result.length() - 1);

            return result;
        } else {
            if (matches(RegularExpressions.FOR_AS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_AS.getCharactersToSubtract());
                result += RegularExpressions.FOR_AS.getDativeEnding();

            }  else if (matches(RegularExpressions.FOR_US, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_US.getCharactersToSubtract());
                result += RegularExpressions.FOR_US.getDativeEnding();

            } else if (matches(RegularExpressions.FOR_TIS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_TIS.getCharactersToSubtract());
                result += RegularExpressions.FOR_TIS.getDativeEnding();

            } else if (matches(RegularExpressions.FOR_IYS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_IYS.getCharactersToSubtract());
                result += RegularExpressions.FOR_IYS.getDativeEnding();

            } else if (matches(RegularExpressions.FOR_A, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_A.getCharactersToSubtract());
                result += RegularExpressions.FOR_A.getDativeEnding();

            } else if (matches(RegularExpressions.FOR_E, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_E.getCharactersToSubtract());
                result += RegularExpressions.FOR_E.getDativeEnding();

            }  else if (matches(RegularExpressions.FOR_DYS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_DYS.getCharactersToSubtract());
                result += RegularExpressions.FOR_DYS.getDativeEnding();
            }  else {
                return wordInNominativeCase;
            }
        }

        result = result.toLowerCase();
        if (isUpper) {
            firstLetter = result.substring(0, 1).toUpperCase();
        } else {
            firstLetter = result.substring(0, 1).toLowerCase();
        }
        result = firstLetter + result.substring(1);

        return result;
    }

    private  static String getInstrumental(String wordInNominativeCase){
        String firstLetter = null;
        boolean isUpper = Character.isUpperCase(wordInNominativeCase.charAt(0));
        wordInNominativeCase = wordInNominativeCase.trim();
        String result = wordInNominativeCase.toLowerCase();

        String[] tokens = wordInNominativeCase.split(" ");

        if(tokens.length > 1){
            result = "";

            for (String token : tokens){
                result += getInstrumental(token) + " ";
            }

            result = result.substring(0, result.length() - 1);

            return result;
        } else {
            if (matches(RegularExpressions.FOR_AS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_AS.getCharactersToSubtract());
                result += RegularExpressions.FOR_AS.getInstrumentalEnding();

            }  else if (matches(RegularExpressions.FOR_US, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_US.getCharactersToSubtract());
                result += RegularExpressions.FOR_US.getInstrumentalEnding();

            } else if (matches(RegularExpressions.FOR_TIS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_TIS.getCharactersToSubtract());
                result += RegularExpressions.FOR_TIS.getInstrumentalEnding();

            } else if (matches(RegularExpressions.FOR_IYS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_IYS.getCharactersToSubtract());
                result += RegularExpressions.FOR_IYS.getInstrumentalEnding();

            } else if (matches(RegularExpressions.FOR_A, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_A.getCharactersToSubtract());
                result += RegularExpressions.FOR_A.getInstrumentalEnding();

            } else if (matches(RegularExpressions.FOR_E, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_E.getCharactersToSubtract());
                result += RegularExpressions.FOR_E.getInstrumentalEnding();

            }  else if (matches(RegularExpressions.FOR_DYS, result)) {
                result = wordInNominativeCase.substring(0,
                        wordInNominativeCase.length() - RegularExpressions.FOR_DYS.getCharactersToSubtract());
                result += RegularExpressions.FOR_DYS.getInstrumentalEnding();
            }  else {
                return wordInNominativeCase;
            }
        }

        result = result.toLowerCase();
        if (isUpper) {
            firstLetter = result.substring(0, 1).toUpperCase();
        } else {
            firstLetter = result.substring(0, 1).toLowerCase();
        }
        result = firstLetter + result.substring(1);

        return result;
    }

    private static boolean matches(RegularExpressions regexp, String stringToTest){
        Pattern pattern = Pattern.compile(regexp.getRegexp());
        Matcher matcher = pattern.matcher(stringToTest);

        return matcher.matches();
    }
}